package com.property.demo.service.impl;

import com.property.demo.model.Complaint;
import com.property.demo.model.Owner;
import com.property.demo.repository.ComplaintRepository;
import com.property.demo.repository.OwnerRepository;
import com.property.demo.service.ComplaintService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.criteria.Predicate;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

@Service
public class ComplaintServiceImpl implements ComplaintService {

    @Autowired
    private ComplaintRepository complaintRepository;
    
    @Autowired
    private OwnerRepository ownerRepository;

    @Override
    public List<Complaint> findAll() {
        return complaintRepository.findAll();
    }

    @Override
    public Page<Complaint> findAll(Pageable pageable) {
        return complaintRepository.findAll(pageable);
    }

    @Override
    public Page<Complaint> findByFilters(Long ownerId, String title, String status, String type, Pageable pageable) {
        Specification<Complaint> spec = (root, query, criteriaBuilder) -> {
            List<Predicate> predicates = new ArrayList<>();
            
            if (ownerId != null) {
                predicates.add(criteriaBuilder.equal(root.get("owner").get("id"), ownerId));
            }
            
            if (title != null && !title.isEmpty()) {
                predicates.add(criteriaBuilder.like(criteriaBuilder.lower(root.get("title")), "%" + title.toLowerCase() + "%"));
            }
            
            if (status != null && !status.isEmpty()) {
                predicates.add(criteriaBuilder.equal(root.get("status"), status));
            }
            
            if (type != null && !type.isEmpty()) {
                predicates.add(criteriaBuilder.equal(root.get("type"), type));
            }
            
            return criteriaBuilder.and(predicates.toArray(new Predicate[0]));
        };
        
        return complaintRepository.findAll(spec, pageable);
    }

    @Override
    public Optional<Complaint> findById(Long id) {
        return complaintRepository.findById(id);
    }

    @Override
    public Complaint save(Complaint complaint) {
        if (complaint.getOwner() != null && complaint.getOwner().getId() != null) {
            Optional<Owner> owner = ownerRepository.findById(complaint.getOwner().getId());
            owner.ifPresent(complaint::setOwner);
        }
        return complaintRepository.save(complaint);
    }

    @Override
    public Complaint update(Long id, Complaint complaintDetails) {
        Optional<Complaint> optionalComplaint = complaintRepository.findById(id);
        if (optionalComplaint.isPresent()) {
            Complaint existingComplaint = optionalComplaint.get();
            
            if (complaintDetails.getOwner() != null && complaintDetails.getOwner().getId() != null) {
                Optional<Owner> owner = ownerRepository.findById(complaintDetails.getOwner().getId());
                owner.ifPresent(existingComplaint::setOwner);
            }
            
            existingComplaint.setTitle(complaintDetails.getTitle());
            existingComplaint.setContent(complaintDetails.getContent());
            existingComplaint.setType(complaintDetails.getType());
            existingComplaint.setStatus(complaintDetails.getStatus());
            existingComplaint.setHandleTime(complaintDetails.getHandleTime());
            existingComplaint.setFinishTime(complaintDetails.getFinishTime());
            existingComplaint.setHandlerName(complaintDetails.getHandlerName());
            existingComplaint.setResult(complaintDetails.getResult());
            
            return complaintRepository.save(existingComplaint);
        }
        return null;
    }

    @Override
    @Transactional
    public void delete(Long id) {
        complaintRepository.deleteById(id);
    }

    @Override
    @Transactional
    public void deleteAll(List<Long> ids) {
        complaintRepository.deleteAllById(ids);
    }

    @Override
    public List<Complaint> findByOwnerId(Long ownerId) {
        return complaintRepository.findByOwnerId(ownerId);
    }

    @Override
    public List<Complaint> findByStatus(String status) {
        return complaintRepository.findByStatus(status);
    }

    @Override
    public List<Complaint> findByType(String type) {
        return complaintRepository.findByType(type);
    }
} 